package gormclient

import (
	"errors"
	"fmt"
	"github.com/glebarez/sqlite"
	"gorm.io/driver/mysql"
	"gorm.io/driver/postgres"
	"gorm.io/gorm"
	"gorm.io/gorm/schema"
	"organoid_public/infrastructure/db"
	logger2 "organoid_public/pkg/logger"
	"time"
)

// DbClient 数据库配置
type DbClient struct {
	clients map[db.Name]*gorm.DB
}

// InitDbClient 初始化数据库客户端
func InitDbClient(conf map[db.Name]db.Database, log logger2.Logger) *DbClient {
	if conf == nil {
		panic(errors.New("数据库配置不能为空"))
	}

	c := &DbClient{clients: make(map[db.Name]*gorm.DB)}

	for key, item := range conf {
		c.openDb(key, item, log)
	}

	return c

}

// GetDb 获取数据库连接
func (d *DbClient) GetDb(key ...db.Name) *gorm.DB {
	if len(key) == 0 || key[0] == "" {
		return d.clients[db.NameDefault]
	}

	return d.clients[key[0]]
}

// 创建数据库会话
func (d *DbClient) openDb(dbName db.Name, database db.Database, log2 logger2.Logger) {
	//newLogger := logger.New(
	//	log.New(os.Stdout, "\r\n[SQL]", log.LstdFlags), // io writer
	//	//log2.NewSql(), // io writer
	//	logger.Config{
	//		SlowThreshold:             time.Second, // Slow SQL threshold
	//		LogLevel:                  logger.Info, // Log level
	//		IgnoreRecordNotFoundError: true,        // Ignore ErrRecordNotFound error for logger
	//		ParameterizedQueries:      true,        // Don't include params in the SQL log
	//		Colorful:                  false,       // Disable color
	//	},
	//)
	client, err := gorm.Open(d.getDialect(database), &gorm.Config{
		NamingStrategy: schema.NamingStrategy{
			SingularTable: true,
		},
		//Logger: logger.Default.LogMode(logger.Info),
		//Logger: newLogger,
		Logger: logger2.NewZapSqlLog(log2),
	})

	if err != nil {
		panic(fmt.Sprintf("打开数据库%s时出错：%s", dbName, err.Error()))
	}

	sqlDb, err := client.DB()
	if err != nil {
		panic(fmt.Sprintf("获取数据库实例%s时出错：%s", dbName, err.Error()))
	}

	//设置连接池
	sqlDb.SetMaxIdleConns(100)
	sqlDb.SetMaxOpenConns(1000)
	sqlDb.SetConnMaxLifetime(time.Hour)
	if database.Driver == db.DriverSqlite3 {
		client.Exec("PRAGMA busy_timeout = 10000")
	}
	d.clients[dbName] = client
}

// 获取数据库连接
func (d *DbClient) getDialect(database db.Database) gorm.Dialector {
	switch database.Driver {
	case db.DriverMysql:
		return mysql.Open(database.DSN)
	case db.DriverPostgresql:
		return postgres.Open(database.DSN)
	case db.DriverSqlite3:
		return sqlite.Open(database.DSN)
	default:
		panic("未找到Dialect处理器")
	}
}
